﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using static DW.Library.Win32API;
using Point = System.Windows.Point;

namespace DW.Library
{
    public static class Win32API
    {

        public static readonly HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
        public delegate bool MonitorEnumProc(IntPtr monitor, IntPtr hdc, IntPtr lprcMonitor, IntPtr lParam);

        private const string
            User32 = "User32.dll",
            Shell32 = "Shell32.dll",
             Kernel32 = "kernel32.dll",
             Advapi32 = "advapi32.dll",
            ShCore = "ShCore.dll",
            Dwmapi = "Dwmapi.dll";
        // 控制改变屏幕分辨率的常量
        public const int ENUM_CURRENT_SETTINGS = -1;
        public const int CDS_UPDATEREGISTRY = 0x01;
        public const int CDS_NORESET = 0x10000000;
        public const int CDS_TEST = 0x02;
        public const int DISP_CHANGE_SUCCESSFUL = 0;
        public const int DISP_CHANGE_RESTART = 1;
        public const int DISP_CHANGE_FAILED = -1;
        public const int DISP_CHANGE_BADMODE = -2;
        public const int DISP_CHANGE_NOTUPDATED = -3;
        public const int DISP_CHANGE_BADFLAGS = -4;
        public const int DISP_CHANGE_BADPARAM = -5;

        public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
        public static readonly IntPtr HWND_TOP = new IntPtr(0);
        public static readonly IntPtr HWND_NOTTOPMOST = new IntPtr(-2);
        public static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
        public const Int32 WM_NCHITTEST = 0x0084;
        public const uint GW_HWNDNEXT = 2;

        /// <summary> 传入窗口消息通用编码 </summary>
        public const int WM_COPYDATA = 0x004A;

        public const int GWL_STYLE = -16;

        public const long WS_BORDER = 0x00800000L;
        public const int WS_THICKFRAME = 0x00040000;
        public const uint SWP_FRAMECHANGED = 0x0020;

        // 常量
        public const int SW_SHOWNORMAL = 1;
        public const int SW_SHOWMINIMIZED = 2;
        public const int SW_SHOWMAXIMIZED = 3;
        public enum WM
        {
            NULL = 0x0000,
            CREATE = 0x0001,
            DESTROY = 0x0002,
            MOVE = 0x0003,
            SIZE = 0x0005,
            ACTIVATE = 0x0006,
            SETFOCUS = 0x0007,
            KILLFOCUS = 0x0008,
            ENABLE = 0x000A,
            SETREDRAW = 0x000B,
            SETTEXT = 0x000C,
            GETTEXT = 0x000D,
            GETTEXTLENGTH = 0x000E,
            PAINT = 0x000F,
            CLOSE = 0x0010,
            QUERYENDSESSION = 0x0011,
            QUIT = 0x0012,
            QUERYOPEN = 0x0013,
            ERASEBKGND = 0x0014,
            SYSCOLORCHANGE = 0x0015,
            SHOWWINDOW = 0x0018,
            CTLCOLOR = 0x0019,
            WININICHANGE = 0x001A,
            SETTINGCHANGE = WININICHANGE,
            ACTIVATEAPP = 0x001C,
            SETCURSOR = 0x0020,
            MOUSEACTIVATE = 0x0021,
            CHILDACTIVATE = 0x0022,
            QUEUESYNC = 0x0023,
            GETMINMAXINFO = 0x0024,

            WINDOWPOSCHANGING = 0x0046,
            WINDOWPOSCHANGED = 0x0047,

            CONTEXTMENU = 0x007B,
            STYLECHANGING = 0x007C,
            STYLECHANGED = 0x007D,
            DISPLAYCHANGE = 0x007E,
            GETICON = 0x007F,
            SETICON = 0x0080,
            NCCREATE = 0x0081,
            NCDESTROY = 0x0082,
            NCCALCSIZE = 0x0083,
            NCHITTEST = 0x0084,
            NCPAINT = 0x0085,
            NCACTIVATE = 0x0086,
            GETDLGCODE = 0x0087,
            SYNCPAINT = 0x0088,
            NCMOUSEMOVE = 0x00A0,
            NCLBUTTONDOWN = 0x00A1,
            NCLBUTTONUP = 0x00A2,
            NCLBUTTONDBLCLK = 0x00A3,
            NCRBUTTONDOWN = 0x00A4,
            NCRBUTTONUP = 0x00A5,
            NCRBUTTONDBLCLK = 0x00A6,
            NCMBUTTONDOWN = 0x00A7,
            NCMBUTTONUP = 0x00A8,
            NCMBUTTONDBLCLK = 0x00A9,

            SYSKEYDOWN = 0x0104,
            SYSKEYUP = 0x0105,
            SYSCHAR = 0x0106,
            SYSDEADCHAR = 0x0107,
            COMMAND = 0x0111,
            SYSCOMMAND = 0x0112,

            MOUSEMOVE = 0x0200,
            LBUTTONDOWN = 0x0201,
            LBUTTONUP = 0x0202,
            LBUTTONDBLCLK = 0x0203,
            RBUTTONDOWN = 0x0204,
            RBUTTONUP = 0x0205,
            RBUTTONDBLCLK = 0x0206,
            MBUTTONDOWN = 0x0207,
            MBUTTONUP = 0x0208,
            MBUTTONDBLCLK = 0x0209,
            MOUSEWHEEL = 0x020A,
            XBUTTONDOWN = 0x020B,
            XBUTTONUP = 0x020C,
            XBUTTONDBLCLK = 0x020D,
            MOUSEHWHEEL = 0x020E,
            PARENTNOTIFY = 0x0210,

            CAPTURECHANGED = 0x0215,
            POWERBROADCAST = 0x0218,
            DEVICECHANGE = 0x0219,

            ENTERSIZEMOVE = 0x0231,
            EXITSIZEMOVE = 0x0232,

            IME_SETCONTEXT = 0x0281,
            IME_NOTIFY = 0x0282,
            IME_CONTROL = 0x0283,
            IME_COMPOSITIONFULL = 0x0284,
            IME_SELECT = 0x0285,
            IME_CHAR = 0x0286,
            IME_REQUEST = 0x0288,
            IME_KEYDOWN = 0x0290,
            IME_KEYUP = 0x0291,

            NCMOUSELEAVE = 0x02A2,

            TABLET_DEFBASE = 0x02C0,

            // WM_TABLET_MAXOFFSET = 0x20,
            TABLET_ADDED = TABLET_DEFBASE + 8,
            TABLET_DELETED = TABLET_DEFBASE + 9,
            TABLET_FLICK = TABLET_DEFBASE + 11,
            TABLET_QUERYSYSTEMGESTURESTATUS = TABLET_DEFBASE + 12,

            CUT = 0x0300,
            COPY = 0x0301,
            PASTE = 0x0302,
            CLEAR = 0x0303,
            UNDO = 0x0304,
            RENDERFORMAT = 0x0305,
            RENDERALLFORMATS = 0x0306,
            DESTROYCLIPBOARD = 0x0307,
            DRAWCLIPBOARD = 0x0308,
            PAINTCLIPBOARD = 0x0309,
            VSCROLLCLIPBOARD = 0x030A,
            SIZECLIPBOARD = 0x030B,
            ASKCBFORMATNAME = 0x030C,
            CHANGECBCHAIN = 0x030D,
            HSCROLLCLIPBOARD = 0x030E,
            QUERYNEWPALETTE = 0x030F,
            PALETTEISCHANGING = 0x0310,
            PALETTECHANGED = 0x0311,
            HOTKEY = 0x0312,
            PRINT = 0x0317,
            PRINTCLIENT = 0x0318,
            APPCOMMAND = 0x0319,
            THEMECHANGED = 0x031A,

            DWMCOMPOSITIONCHANGED = 0x031E,
            DWMNCRENDERINGCHANGED = 0x031F,
            DWMCOLORIZATIONCOLORCHANGED = 0x0320,
            DWMWINDOWMAXIMIZEDCHANGE = 0x0321,

            GETTITLEBARINFOEX = 0x033F,

            DWMSENDICONICTHUMBNAIL = 0x0323,
            DWMSENDICONICLIVEPREVIEWBITMAP = 0x0326,

            USER = 0x0400,

            /// <summary>
            /// This is the hard-coded message value used by WinForms for Shell_NotifyIcon.
            /// It's relatively safe to reuse.
            /// </summary>
            TRAYMOUSEMESSAGE = 0x800, // WM_USER + 1024
            APP = 0x8000,
        }

        public enum ABEdge
        {
            Left = 0,
            Top,
            Right,
            Bottom,
            None
        }
        [System.Flags]
        internal enum DWMNCRenderingPolicy
        {
            UseWindowStyle = 0,
            Disabled,
            Enabled,
            Last
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct APPBARDATA
        {
            public int cbSize;
            public IntPtr hWnd;
            public int uCallbackMessage;
            public int uEdge;
            public RECT rc;
            public IntPtr lParam;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct POINT
        {
            public int X;
            public int Y;

            public static explicit operator POINT(Point p)
            {
                return new POINT { X = (int)p.X, Y = (int)p.Y };
            }

            public static explicit operator Point(POINT r)
            {
                return new Point(r.X, r.Y);
            }
        }
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct RECTL
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;

            public RECT(int left, int top, int right, int bottom)
            {
                this.left = left;
                this.top = top;
                this.right = right;
                this.bottom = bottom;
            }

            public int Width
            {
                get { return right - left; }
            }

            public int Height
            {
                get { return bottom - top; }
            }

            public void Offset(int dx, int dy)
            {
                left += dx;
                top += dy;
                right += dx;
                bottom += dy;
            }

            public bool IsEmpty
            {
                get
                {
                    return left >= right || top >= bottom;
                }
            }
            public Point Location
            {
                get
                {
                    return new Point(left, top);
                }
                set
                {
                    left = (int)value.X;
                    top = (int)value.Y;
                }
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct WINDOWPOS
        {
            public IntPtr hwnd;
            public IntPtr hwndInsertAfter;
            public int x;
            public int y;
            public int cx;
            public int cy;
            public int flags;

            public Rectangle Bounds
            {
                get { return new Rectangle(x, y, cx, cy); }
                set
                {
                    x = (int)value.X;
                    y = (int)value.Y;
                    cx = (int)value.Width;
                    cy = (int)value.Height;
                }
            }
        }

        public const int
            SWP_NOMOVE = 0x0002,
            SWP_NOSIZE = 0x0001,
            SWP_NOZORDER = 0x0004,
            SWP_NOOWNERZORDER = 0x0200,
        SWP_NOACTIVATE = 0x0010;

        public const int
            WM_SIZE = 0x0005,
            WM_ACTIVATE = 0x0006,
            WM_WINDOWPOSCHANGED = 0x0047,
            WM_SHOWWINDOW = 0x0018,
            WM_SYSCOMMAND = 0x0112,
            WM_WINDOWPOSCHANGING = 0x0046,
            WM_GETMINMAXINFO = 0x0024,
            WM_NCCALCSIZE = 0x0083;
        public const int WM_PAINT = 0x000F;
        public const int WM_PAINTICON = 0x0026;
        public const int WM_NCACTIVATE = 0x0086;

        public const int
            SC_MOVE = 0xF010;

        public const int
            SIZE_MINIMIZED = 1;

        public const int
            DWMWA_EXTENDED_FRAME_BOUNDS = 9;

        public static int SC_FROM_WPARAM(IntPtr wparam)
        {
            // In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by
            // the system. To obtain the correct result when testing the value of wParam, an application must
            // combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.
            return ((int)wparam & 0xfff0);
        }

        public enum ABM
        {
            NEW = 0,
            REMOVE,
            QUERYPOS,
            SETPOS,
            GETSTATE,
            GETTASKBARPOS,
            ACTIVATE,
            GETAUTOHIDEBAR,
            SETAUTOHIDEBAR,
            WINDOWPOSCHANGED,
            SETSTATE
        }

        [StructLayout(LayoutKind.Sequential)]
        internal class MINMAXINFO
        {
            public POINT ptReserved;
            public POINT ptMaxSize;
            public POINT ptMaxPosition;
            public POINT ptMinTrackSize;
            public POINT ptMaxTrackSize;
        }

        public enum ABN
        {
            STATECHANGE = 0,
            POSCHANGED,
            FULLSCREENAPP,
            WINDOWARRANGE
        }

        public const int
            GWL_EXSTYLE = -20;


        public const int
            GWLP_WNDPROC = -4;

        public const int
            WS_EX_TOOLWINDOW = 0x00000080;


        [DllImport(Shell32, ExactSpelling = true)]
        public static extern uint SHAppBarMessage(ABM dwMessage, ref APPBARDATA pData);

        [DllImport(User32, CharSet = CharSet.Unicode)]
        public static extern int RegisterWindowMessage(string msg);

        [DllImport(User32, ExactSpelling = true, SetLastError = true)]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint flags);

        public static IntPtr GetWindowLongPtr(IntPtr hWnd, int index)
            => IntPtr.Size == 4 ? GetWindowLongPtr32(hWnd, index) : GetWindowLongPtr64(hWnd, index);

        [DllImport(User32, EntryPoint = "CallWindowProcW")]
        public static extern IntPtr CallWindowProcW(nint lpPrevWndProc, IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        [DllImport(User32, EntryPoint = "GetWindowLong")]
        private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int index);

        [DllImport(User32, EntryPoint = "GetWindowLongPtr", SetLastError = true)]
        private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int index);

        public static IntPtr SetWindowLongPtr(IntPtr hWnd, int index, IntPtr newLong)
            => IntPtr.Size == 4 ? SetWindowLongPtr32(hWnd, index, newLong) : SetWindowLongPtr64(hWnd, index, newLong);

        [DllImport(User32, EntryPoint = "SetWindowLong")]
        private static extern IntPtr SetWindowLongPtr32(IntPtr hWnd, int index, IntPtr newLong);

        [DllImport(User32, EntryPoint = "SetWindowLongPtr")]
        private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int index, IntPtr newLong);

        [DllImport(User32, SetLastError = true)]
        public static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);

        [DllImport(User32, SetLastError = true)]
        public static extern bool PtInRect(RECT rect, POINT point);

        [DllImport(User32, SetLastError = true)]
        public static extern bool IntersectRect(out RECT rect, RECT rectA, RECT rectB);

        [DllImport(Dwmapi)]
        public static extern int DwmGetWindowAttribute(IntPtr hWnd, uint dwAttribute, out RECT pvAttribute, int cbAttribute);

        [DllImport("dwmapi.dll")]
        internal static extern int DwmSetWindowAttribute(IntPtr hWnd, int attr, ref int attrValue, int attrSize);
        [DllImport("user32.dll")]
        public static extern int GetDisplayConfigBufferSizes(int flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
        [DllImport("user32.dll")]
        public static extern int QueryDisplayConfig([In] int flags, [In, Out] ref uint numPathArrayElements, [Out] DisplayConfigPathInfo[] pathInfoArray,
                                      [In, Out] ref uint numModeInfoArrayElements, [Out] DisplayConfigModeInfo[] modeInfoArray, IntPtr currentTopologyId);
        [DllImport("user32.dll")]
        public static extern int QueryDisplayConfig([In] int flags, [In, Out] ref uint numPathArrayElements, [Out] DisplayConfigPathInfo_DPI[] pathInfoArray,
                                      [In, Out] ref uint numModeInfoArrayElements, [Out] DisplayConfigModeInfo[] modeInfoArray, IntPtr currentTopologyId);
        [DllImport(User32, ExactSpelling = true, CharSet = CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetSystemMetrics(int nIndex);

        [DllImport(User32, CharSet = CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool SystemParametersInfo(int nAction, int nParam, ref RECT rc, int nUpdate);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);

        [DllImport("user32.dll")]
        public static extern int DisplayConfigGetDeviceInfo(ref DisplayConfigDeviceScaleHeader request);
        [DllImport("user32.dll")]
        public static extern int DisplayConfigGetDeviceInfo(ref DisplayConfigDeviceInfoNameHeader request);
        [DllImport(User32, ExactSpelling = true)]
        [ResourceExposure(ResourceScope.None)]
        public static extern IntPtr MonitorFromPoint(POINTSTRUCT pt, int flags);

        [DllImport(User32, ExactSpelling = true)]
        [ResourceExposure(ResourceScope.None)]
        public static extern IntPtr MonitorFromWindow(HandleRef handle, int flags);

        [DllImport(User32, EntryPoint = "FindWindowEx")]
        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
        [DllImport(User32, CharSet = CharSet.Auto)]
        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
        [DllImport(Kernel32)]
        public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
        [DllImport(User32, CharSet = CharSet.Unicode, EntryPoint = "SendMessage")]
        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
        public static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
        [DllImport("User32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
        [DllImport(User32, CharSet = CharSet.Auto)]
        public static extern bool GetCursorPos(out POINT pt);
        [DllImport(User32)]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
        [DllImport(User32)]
        public static extern IntPtr WindowFromPhysicalPoint(POINT pt);
        public static bool SetWindowPosEx(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags)
        {
            return SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
        }
        public static bool SetWindowPosEx(IntPtr hWnd, IntPtr hWndInsertAfter, double X, double Y, double cx, double cy, int uFlags)
        {
            return SetWindowPosEx(hWnd, hWndInsertAfter, (int)X, (int)Y, (int)cx, (int)cy, uFlags);
        }
        public static bool SetWindowPosEx(IntPtr hWnd, IntPtr hWndInsertAfter, Rect rect, int uFlags)
        {
            return SetWindowPosEx(hWnd, hWndInsertAfter, rect.X, rect.Y, rect.Width, rect.Height, uFlags);
        }
        [DllImport(Kernel32, SetLastError = true)]
        public static extern bool CloseHandle(IntPtr hHandle);
        [DllImport(Kernel32, CharSet = CharSet.Unicode)]
        public static extern bool QueryFullProcessImageName(IntPtr hprocess, int dwFlags, StringBuilder lpExeName, out int size);

        [DllImport(User32)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumChildWindows(IntPtr parentHandle, EnumWindowsProc callback, IntPtr lParam);
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData; //可以是任意值
            public int cbData;    //指定lpData内存区域的字节数
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData; //发送给目录窗口所在进程的数据
        }
        public enum WM_NCHITTEST_Result : int
        {
            HTCAPTION = 2,
            HTREDUCE = 8,
            HTMAXBUTTON = 9,
            HTTOP = 12,

        }
        [Flags]
        public enum MONITORINFOF
        {
            PRIMARY = 0x1
        }

        [Flags]
        public enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VirtualMemoryOperation = 0x00000008,
            VirtualMemoryRead = 0x00000010,
            VirtualMemoryWrite = 0x00000020,
            DuplicateHandle = 0x00000040,
            CreateProcess = 0x000000080,
            SetQuota = 0x00000100,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            ProcessQueryLimitedInformation = 0x00001000,
            Synchronize = 0x00100000,
            VmRead = 0x0010,
        }
        [Flags]
        public enum QueryDeviceConfigFlags : uint
        {
            QdcAllPaths = 0x00000001,
            QdcOnlyActivePaths = 0x00000002,
            QdcDatabaseCurrent = 0x00000004,
            QDC_VIRTUAL_MODE_AWARE = 0x00000010
        }
        [Flags]
        public enum MONITOR_DPI_TYPE
        {
            MDT_EFFECTIVE_DPI = 0,
            MDT_ANGULAR_DPI = 1,
            MDT_RAW_DPI = 2,
            MDT_DEFAULT = MDT_EFFECTIVE_DPI
        }

        private const int CCHDEVICENAME = 32;

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct MONITORINFOEX
        {
            public int cbSize;
            public RECT rcMonitor;
            public RECT rcWork;
            public MONITORINFOF dwFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
            public string szDevice;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
        public class MONITORINFOEX1
        {
            public int cbSize = Marshal.SizeOf(typeof(MONITORINFOEX));
            public RECT rcMonitor = new RECT();
            public RECT rcWork = new RECT();
            public int dwFlags = 0;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public char[] szDevice = new char[32];
        }

        [DllImport("ChangeResoLib.dll", EntryPoint = "ChangeResolution", CharSet = CharSet.Unicode)]
        public extern static int ChangeResolution();


        public delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData);
        [DllImport("User32.dll")]
        public static extern StatusCode SetDisplayConfig(int numPathArrayElements, [In] DisplayConfigPathInfo[] pathArray,
            int numModeInfoArrayElements, [In] DisplayConfigModeInfo[] modeInfoArray, int flags);
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern long SetDisplayConfig(uint numPathArrayElements, IntPtr pathArray, uint numModeArrayElements, IntPtr modeArray, uint flags);

        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();

        [DllImport("user32.dll")]
        public static extern int ChangeDisplaySettings([In] ref DEVMODE lpDevMode, int dwFlags);
        [DllImport("user32.dll", EntryPoint = "ChangeDisplaySettingsEx")]
        public static extern int ChangeDisplaySettingsEx([In] string deviceName, [In] ref DEVMODE lpDevMode, IntPtr hwnd, int dwFlags, IntPtr lParam);

        [DllImport(User32, CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetMonitorInfo(IntPtr hMonitor, [In, Out] MONITORINFOEX1 lpmi);




        [DllImport(User32)]
        public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);
        [DllImport(User32, ExactSpelling = true)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool EnumDisplayMonitors(HandleRef hdc, COMRECT rcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);
        [DllImport(ShCore, ExactSpelling = true, PreserveSig = false)]
        public static extern void GetDpiForMonitor(IntPtr hMonitor, MONITOR_DPI_TYPE dpiType, out int dpiX, out int dpiY);

        [DllImport(User32, CharSet = CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool GetMonitorInfo(HandleRef hmonitor, [In, Out] MONITORINFOEX info);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetMonitorInfo(IntPtr hMonitor, [In, Out] MONITORINFOEX lpmi);
        [DllImport("user32.dll", CharSet = CharSet.Ansi)]
        public static extern bool EnumDisplaySettings(
                         string lpszDeviceName,
                         int iModeNum,
                         ref DEVMODE lpDevMode);
        [DllImport(User32)]
        public static extern IntPtr SetParent(IntPtr hwnd, IntPtr parentHwnd);
        [DllImportAttribute(User32, EntryPoint = "MoveWindow")]
        public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
        [DllImport(User32)]
        private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
        public static bool ShowWindow(IntPtr hwnd, ShowWindowCommand showWindowCommand)
        {
            return ShowWindow(hwnd, (int)showWindowCommand);
        }
        public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);
        [DllImport(User32)]
        public static extern bool EnumWindows(EnumWindowsProc proc, IntPtr lParam);
        [DllImport(User32)]
        public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        [DllImport(User32, CharSet = CharSet.Unicode)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder lptrString, int nMaxCount);
        [DllImport(User32)]
        public static extern bool IsWindowVisible(IntPtr hWnd);
        [DllImport(Kernel32, SetLastError = true)]
        public static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);
        [DllImport(Advapi32, SetLastError = true)]
        public static extern bool GetTokenInformation(IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, ref TOKEN_ELEVATION TokenInformation, int tokenInformationLength, out int returnLength);
        [DllImport(User32)]
        public static extern IntPtr GetWindow(IntPtr hWnd, uint wCmd);
        [DllImport("user32")]
        public static extern bool IsZoomed(IntPtr hWnd);
        [DllImport("user32")]
        public static extern bool IsIconic(IntPtr hWnd);

        /// <summary>   
        /// 该函数返回指定窗口的显示状态以及被恢复的、最大化的和最小化的窗口位置。   
        /// </summary>   
        [DllImport("User32.dll")]
        public static extern int GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT wp);
        /// <summary>   
        /// 设置指定窗口的显示状态以及被恢复的、最大化的和最小化的窗口位置。   
        /// </summary>   
        [DllImport("User32.dll")]
        public static extern bool SetWindowPlacement(IntPtr hWnd, WINDOWPLACEMENT wp);

        [StructLayout(LayoutKind.Sequential)]
        public struct WINDOWPLACEMENT
        {
            public int length;
            public int flags;
            public int showCmd;
            public POINT ptMinPosition;
            public POINT ptMaxPosition;
            public RECT rcNormalPosition;
        }
        public enum TOKEN_INFORMATION_CLASS
        {
            TokenElevation = 20,
            TokenElevationType
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct TOKEN_ELEVATION
        {
            public int TokenIsElevated;
        }
        public enum ShowWindowCommand
        {
            SW_HIDE = 0,
            SW_SHOWNORMAL = 1,
            SW_NORMAL = 1,
            SW_SHOWMINIMIZED = 2,
            SW_SHOWMAXIMIZED = 3,
            SW_MAXIMIZE = 3,
            SW_SHOWNOACTIVATE = 4,
            SW_SHOW = 5,
            SW_MINIMIZE = 6,
            SW_SHOWMINNOACTIVE = 7,
            SW_SHOWNA = 8,
            SW_RESTORE = 9,
            SW_SHOWDEFAULT = 10,
            SW_FORCEMINIMIZE = 11
        }
        public enum DEVMODE_SETTINGS
        {
            ENUM_CURRENT_SETTINGS = (-1),
            ENUM_REGISTRY_SETTINGS = (-2)
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayConfigPathInfo_DPI
        {
            public DisplayConfigPathSourceInfo sourceInfo;
            public DisplayConfigPathTargetInfo targetInfo;
            public uint Flags;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayConfigPathInfo
        {
            public DisplayConfigPathSourceInfo sourceInfo;
            public DisplayConfigPathTargetMode targetInfo;
            public DisplayConfigFlags flags;
        }
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct DisplayConfigPathSourceInfo
        {
            public LUID AdapterId;
            public uint Id;
            public uint ModeInfoIdx;
            public uint StatusFlags;
        }
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct DisplayConfigPathTargetInfo
        {
            public LUID adapterId;
            public uint id;
            public Union modeInfoIdxOrStruct;
            public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
            public DISPLAYCONFIG_ROTATION rotation;
            public DISPLAYCONFIG_SCALING scaling;
            public DISPLAYCONFIG_RATIONAL refreshRate;
            public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
            public bool targetAvailable;
            public uint statusFlags;
        }
        [Flags]
        public enum DisplayConfigFlags : uint
        {
            Zero = 0x0,
            PathActive = 0x00000001
        }
        [StructLayout(LayoutKind.Explicit)]
        public struct DisplayConfigModeInfo
        {
            [FieldOffset((0))] public DisplayConfigModeInfoType infoType;

            [FieldOffset(4)] public uint id;

            [FieldOffset(8)] public LUID adapterId;

            [FieldOffset(16)] public DisplayConfigTargetMode targetMode;

            [FieldOffset(16)] public DisplayConfigPathSourceMode sourceMode;

            [FieldOffset(16)] public DISPLAYCONFIG_DESKTOP_IMAGE_INFO desktopImageInfo;
        }
        [Flags]
        public enum DisplayConfigModeInfoType : uint
        {
            Zero = 0,

            Source = 1,
            Target = 2,
            DESKTOP_IMAGE = 3,
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct LUID
        {
            public uint LowPart;
            public int HighPart;

            public override string ToString()
            {
                return (string.Format("{0}{1}", LowPart, HighPart));
            }

            public static explicit operator int(LUID value)
            {
                return (int)(value.LowPart + value.HighPart);
            }
        }

        //[StructLayout(LayoutKind.Sequential, Pack = 4)]
        [StructLayout(LayoutKind.Explicit)]
        public struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO
        {
            [FieldOffset((0))] public PointL PathSourceSize;
            [FieldOffset((8))] public RECTL DesktopImageRegion;
            [FieldOffset((24))] public RECTL DesktopImageClip;

        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct DisplayConfigPathSourceMode
        {
            public int width;
            public int height;
            public DisplayConfigPixelFormat pixelFormat;
            public PointL position;

        }
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct PointL
        {
            public int x;
            public int y;
        }
        [Flags]
        public enum DisplayConfigPixelFormat : uint
        {
            Zero = 0x0,

            Pixelformat8Bpp = 1,
            Pixelformat16Bpp = 2,
            Pixelformat24Bpp = 3,
            Pixelformat32Bpp = 4,
            PixelformatNongdi = 5,
        }
        [Flags]
        public enum DisplayConfigSourceStatus
        {
            Zero = 0x0,
            InUse = 0x00000001
        }
        public enum DISPLAYCONFIG_PIXELFORMAT
        {
            DISPLAYCONFIG_PIXELFORMAT_8BPP = 1,
            DISPLAYCONFIG_PIXELFORMAT_16BPP = 2,
            DISPLAYCONFIG_PIXELFORMAT_24BPP = 3,
            DISPLAYCONFIG_PIXELFORMAT_32BPP = 4,
            DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5,
            DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = unchecked((int)0xFFFFFFFF)
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct DisplayConfigTargetMode
        {
            public DisplayConfigVideoSignalInfo targetVideoSignalInfo;
        }
        [StructLayout(LayoutKind.Explicit)]
        public struct DisplayConfigPathTargetMode
        {
            [FieldOffset(0)] public LUID adapterId;
            [FieldOffset(8)] public uint id;
            [FieldOffset(12)] public uint modeInfoIdx;
            [FieldOffset(16)] public DUMMYSTRUCTNAME unionMember;
            [FieldOffset(20)] public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
            [FieldOffset(24)] public DISPLAYCONFIG_ROTATION rotation;
            [FieldOffset(28)] public DISPLAYCONFIG_SCALING scaling;
            [FieldOffset(32)] public DisplayConfigRational refreshRate;
            [FieldOffset(40)] public DisplayConfigScanLineOrdering scanLineOrdering;

            [FieldOffset(44)] public bool targetAvailable;
            [FieldOffset(48)] public DisplayConfigTargetStatus statusFlags;
        }
        //[StructLayout(LayoutKind.Sequential)]
        //public struct DisplayConfigPathTargetMode
        //{
        //    public LUID adapterId;
        //    public uint id;
        //    public uint modeInfoIdx;
        //    public DummyUnion unionMember;
        //    public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
        //    public DISPLAYCONFIG_ROTATION rotation;
        //    public DISPLAYCONFIG_SCALING scaling;
        //    public DisplayConfigRational refreshRate;
        //    public DisplayConfigScanLineOrdering scanLineOrdering;

        //    public bool targetAvailable;
        //    public DisplayConfigTargetStatus statusFlags;
        //}
        [StructLayout(LayoutKind.Explicit)]
        public struct DummyUnion
        {
            [FieldOffset(0)]
            public uint ModeInfoIdx;
            [FieldOffset(4)]
            public DUMMYSTRUCTNAME DUMMYSTRUCTNAME;
        }
        [StructLayout(LayoutKind.Explicit)]
        public struct DUMMYSTRUCTNAME
        {
            [FieldOffset(0)] public uint desktopModeInfoIdx;
            [FieldOffset(16)] public uint targetModeInfoIdx;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayConfigVideoSignalInfo
        {
            public long pixelRate;
            public DisplayConfigRational hSyncFreq;
            public DisplayConfigRational vSyncFreq;
            public DisplayConfig2DRegion activeSize;
            public DisplayConfig2DRegion totalSize;

            public D3DmdtVideoSignalStandard videoStandard;
            public DisplayConfigScanLineOrdering scanLineOrdering;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayConfigRational
        {
            public uint numerator;
            public uint denominator;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayConfig2DRegion
        {
            public uint cx;
            public uint cy;
        }
        [StructLayout(LayoutKind.Explicit)]
        public struct Union
        {
            [FieldOffset(0)]
            public uint modeInfoIdx;

            [FieldOffset(0)]
            public StructNested nested;
        }
        [Flags]
        public enum DisplayConfigTargetStatus : uint
        {
            Zero = 0x0,

            InUse = 0x00000001,
            Forcible = 0x00000002,
            ForcedAvailabilityBoot = 0x00000004,
            ForcedAvailabilityPath = 0x00000008,
            ForcedAvailabilitySystem = 0x00000010,
        }
        [Flags]
        public enum DisplayConfigScanLineOrdering : uint
        {
            Unspecified = 0,
            Progressive = 1,
            Interlaced = 2,
            InterlacedUpperfieldfirst = Interlaced,
            InterlacedLowerfieldfirst = 3,
        }
        [Flags]
        public enum D3DmdtVideoSignalStandard : uint
        {
            Uninitialized = 0,
            VesaDmt = 1,
            VesaGtf = 2,
            VesaCvt = 3,
            Ibm = 4,
            Apple = 5,
            NtscM = 6,
            NtscJ = 7,
            Ntsc443 = 8,
            PalB = 9,
            PalB1 = 10,
            PalG = 11,
            PalH = 12,
            PalI = 13,
            PalD = 14,
            PalN = 15,
            PalNc = 16,
            SecamB = 17,
            SecamD = 18,
            SecamG = 19,
            SecamH = 20,
            SecamK = 21,
            SecamK1 = 22,
            SecamL = 23,
            SecamL1 = 24,
            Eia861 = 25,
            Eia861A = 26,
            Eia861B = 27,
            PalK = 28,
            PalK1 = 29,
            PalL = 30,
            PalM = 31,
            Other = 255
        }
        [Flags]
        public enum SdcFlags : uint
        {
            Zero = 0,

            TopologyInternal = 0x00000001,
            TopologyClone = 0x00000002,
            TopologyExtend = 0x00000004,
            TopologyExternal = 0x00000008,
            TopologySupplied = 0x00000010,

            UseSuppliedDisplayConfig = 0x00000020,
            SDC_ALLOW_CHANGES = 0x00000400,
            SDC_FORCE_MODE_ENUMERATION = 0x00001000,
            SDC_VIRTUAL_MODE_AWARE = 0x00008000,

            DockLeft = 0x00000001,

            SDC_SAVE_TO_DATABASE = 0x00000200,
            Validate = 0x00000040,
            Apply = 0x00000080,
            NoOptimization = 0x00000100,
            SaveToDatabase = 0x00000200,
            AllowChanges = 0x00000400,
            PathPersistIfRequired = 0x00000800,
            ForceModeEnumeration = 0x00001000,
            AllowPathOrderChanges = 0x00002000,

            UseDatabaseCurrent = TopologyInternal | TopologyClone | TopologyExtend | TopologyExternal
        }
        /// <summary>
        /// Use this enum so that you don't have to hardcode magic values.
        /// </summary>
        public enum StatusCode : uint
        {
            Success = 0,
            InvalidParameter = 87,
            NotSupported = 50,
            AccessDenied = 5,
            GenFailure = 31,
            BadConfiguration = 1610,
            InSufficientBuffer = 122,
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct StructNested
        {
            public ushort desktopModeInfoIdx;
            public ushort targetModeInfoIdx;
        }

        public enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY
        {
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = -1,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_WIRED = 16,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_VIRTUAL = 17,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_USB_TUNNEL = 18,
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = unchecked((int)0x80000000),
            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = unchecked((int)0xFFFFFFFF)
        }

        public enum DISPLAYCONFIG_ROTATION
        {
            DISPLAYCONFIG_ROTATION_IDENTITY = 1,
            DISPLAYCONFIG_ROTATION_ROTATE90 = 2,
            DISPLAYCONFIG_ROTATION_ROTATE180 = 3,
            DISPLAYCONFIG_ROTATION_ROTATE270 = 4,
            DISPLAYCONFIG_ROTATION_FORCE_UINT32 = unchecked((int)0xFFFFFFFF)
        }

        public enum DISPLAYCONFIG_SCALING
        {
            DISPLAYCONFIG_SCALING_IDENTITY = 1,
            DISPLAYCONFIG_SCALING_CENTERED = 2,
            DISPLAYCONFIG_SCALING_STRETCHED = 3,
            DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
            DISPLAYCONFIG_SCALING_CUSTOM = 5,
            DISPLAYCONFIG_SCALING_PREFERRED = 128,
            DISPLAYCONFIG_SCALING_FORCE_UINT32 = unchecked((int)0xFFFFFFFF)
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DISPLAYCONFIG_RATIONAL
        {
            public uint numerator;
            public uint denominator;
        }

        public enum DISPLAYCONFIG_SCANLINE_ORDERING
        {
            DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0,
            DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1,
            DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2,
            DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST,
            DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
            DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = unchecked((int)0xFFFFFFFF)
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct DEVMODE
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string dmDeviceName;

            [MarshalAs(UnmanagedType.U2)]
            public UInt16 dmSpecVersion;

            [MarshalAs(UnmanagedType.U2)]
            public UInt16 dmDriverVersion;

            [MarshalAs(UnmanagedType.U2)]
            public UInt16 dmSize;

            [MarshalAs(UnmanagedType.U2)]
            public UInt16 dmDriverExtra;

            [MarshalAs(UnmanagedType.U4)]
            public DEVMODE_Flags dmFields;

            public POINTL dmPosition;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmDisplayOrientation;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmDisplayFixedOutput;

            [MarshalAs(UnmanagedType.I2)]
            public Int16 dmColor;

            [MarshalAs(UnmanagedType.I2)]
            public Int16 dmDuplex;

            [MarshalAs(UnmanagedType.I2)]
            public Int16 dmYResolution;

            [MarshalAs(UnmanagedType.I2)]
            public Int16 dmTTOption;

            [MarshalAs(UnmanagedType.I2)]
            public Int16 dmCollate;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string dmFormName;

            [MarshalAs(UnmanagedType.U2)]
            public UInt16 dmLogPixels;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmBitsPerPel;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmPelsWidth;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmPelsHeight;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmDisplayFlags;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmDisplayFrequency;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmICMMethod;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmICMIntent;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmMediaType;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmDitherType;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmReserved1;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmReserved2;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmPanningWidth;

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dmPanningHeight;
        }
        public enum DEVMODE_Flags
        {
            DM_BITSPERPEL = 0x40000,
            DM_DISPLAYFLAGS = 0x200000,
            DM_DISPLAYFREQUENCY = 0x400000,
            DM_PELSHEIGHT = 0x100000,
            DM_PELSWIDTH = 0x80000,
            DM_POSITION = 0x20
        }

        [StructLayout(LayoutKind.Sequential)]
        public class COMRECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;

            public COMRECT()
            {
            }

            public COMRECT(int left, int top, int right, int bottom)
            {
                this.left = left;
                this.top = top;
                this.right = right;
                this.bottom = bottom;
            }

            public static COMRECT FromXYWH(int x, int y, int width, int height)
            {
                return new COMRECT(x, y, x + width, y + height);
            }

            public override string ToString()
            {
                return "Left = " + left + " Top " + top + " Right = " + right + " Bottom = " + bottom;
            }
        }

        public struct POINTL
        {
            public Int32 x;
            public Int32 y;
        }

        // use this in cases where the Native API takes a POINT not a POINT*
        // classes marshal by ref.
        [StructLayout(LayoutKind.Sequential)]
        public struct POINTSTRUCT
        {
            public int x;
            public int y;
            public POINTSTRUCT(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }
        public const int SM_CMONITORS = 80,
                      SM_CXSCREEN = 0,
                      SM_CYSCREEN = 1,
                      SPI_GETWORKAREA = 48;


        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct DISPLAY_DEVICE
        {
            [MarshalAs(UnmanagedType.U4)]
            public int cb;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string DeviceName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string DeviceString;
            [MarshalAs(UnmanagedType.U4)]
            public DisplayDeviceStateFlags StateFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string DeviceID;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string DeviceKey;
        }


        [Flags()]
        public enum DisplayDeviceStateFlags : int
        {
            /// <summary>The device is part of the desktop.</summary>
            AttachedToDesktop = 0x1,
            MultiDriver = 0x2,
            /// <summary>The device is part of the desktop.</summary>
            PrimaryDevice = 0x4,
            /// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
            MirroringDriver = 0x8,
            /// <summary>The device is VGA compatible.</summary>
            VGACompatible = 0x10,
            /// <summary>The device is removable; it cannot be the primary display.</summary>
            Removable = 0x20,
            /// <summary>The device has more display modes than its output devices support.</summary>
            ModesPruned = 0x8000000,
            Remote = 0x4000000,
            Disconnect = 0x2000000
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct DisplayConfigSourceDeviceName
        {
            public DisplayConfigDeviceInfoNameHeader Header;
            public DisplayConfigTargetDeviceNameFlags Flags;
            public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY OutputTechnology;
            public ushort EDIDManufactureId;
            public ushort EDIDProductCodeId;
            public uint ConnectorInstance;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public string MonitorFriendDeviceName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string MonitorDevicePath;
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
        public struct DisplayConfigDeviceInfoNameHeader
        {
            public int type;
            public uint size;
            public LUID adapterId;
            public uint id;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string viewGdiDeviceName;
        }

        public enum DISPLAYCONFIG_DEVICE_INFO_TYPE
        {
            DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
            DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
            DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
            // 其他常量
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct DisplayConfigSourceDeviceScale
        {
            public DisplayConfigDeviceScaleHeader Header;
            public DisplayConfigTargetDeviceNameFlags Flags;
            public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY OutputTechnology;
            public ushort EDIDManufactureId;
            public ushort EDIDProductCodeId;
            public uint ConnectorInstance;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public string MonitorFriendDeviceName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string MonitorDevicePath;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayConfigSourceDeviceScale_DPI
        {
            [MarshalAs(UnmanagedType.Struct)]
            public DisplayConfigDeviceInfoHeader Header;
            [field: MarshalAs(UnmanagedType.U4)]
            public int ScaleSteps;

        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayConfigDeviceInfoHeader
        {
            [MarshalAs(UnmanagedType.U4)] public  DisplayConfigDeviceInfoType Type;
            [MarshalAs(UnmanagedType.U4)] public  uint Size;
            [MarshalAs(UnmanagedType.Struct)] public  LUID AdapterId;
            [MarshalAs(UnmanagedType.U4)] public  uint Id;
        }
        public enum DisplayConfigDeviceInfoType
        {
            SetSourceDPIScale = -4,
            GetSourceDPIScale = -3,
            GetSourceName = 1,
            GetTargetName = 2,
            GetTargetPreferredMode = 3,
            GetAdapterName = 4,
            SetTargetPersistence = 5,
            GetTargetBaseType = 6,
            GetSupportVirtualResolution = 7,
            SetSupportVirtualResolution = 8
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
        public struct DisplayConfigDeviceScaleHeader
        {
            public int type;
            public uint size;
            public long adapterId;
            public uint id;

            /// <summary> 最小缩放比例</summary>
            public int minScaleRel;
            /// <summary> 当前缩放比例</summary>
            public int curScaleRel;
            /// <summary> 最大缩放比例</summary>
            public int maxScaleRel;

        }
        public enum DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
        {
            friendlyNameFromEdid,
            friendlyNameForced,
            edidIdsValid,
            reserved,
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayConfigTargetDeviceNameFlags
        {
            public uint Value;
        }
        public enum DISPLAYCONFIG_DEVICE_INFO_TYPE_CUSTOM
        {
            // DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
            DISPLAYCONFIG_DEVICE_INFO_GET_DPI_SCALE =
                -3, // returns min, max, suggested, and currently applied DPI scaling values.
            DISPLAYCONFIG_DEVICE_INFO_SET_DPI_SCALE = -4, // set current dpi scaling value for a display
        };
        public static int MakeLParam(int LoWord, int HiWord)
        {
            return ((HiWord << 16) | (LoWord & 0xffff));
        }
    }
}
